package com.xiaomaoguai.fcp.hsf.autoconfigure;

import lombok.Getter;
import lombok.Setter;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.remoting.support.UrlBasedRemoteAccessor;
import org.springframework.util.Assert;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;

/**
 * @fileName: HsfClientInterceptor.java
 * @author: WeiHui
 * @date: 2018/7/14 15:18
 * @version: v1.0.0
 * @since JDK 1.8
 */
public class HsfClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor {

	@Getter
	@Setter
	private String version;

	private Object hsfProxy;

	/**
	 * 不依赖jar包模式
	 */
	@Getter
	@Setter
	private String hsfServiceInterfaceName;

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		if (this.hsfProxy == null) {
			throw new IllegalStateException("HsfClientInterceptor is not properly initialized - " +
					"invoke 'prepare' before attempting any operations");
		}
		ClassLoader originalClassLoader = overrideThreadContextClassLoader();
		try {
			return invocation.getMethod().invoke(this.hsfProxy, invocation.getArguments());
		} catch (InvocationTargetException ex) {
			Throwable targetEx = ex.getTargetException();
			if (targetEx instanceof InvocationTargetException) {
				targetEx = ((InvocationTargetException) targetEx).getTargetException();
			}
			throw targetEx;
		} catch (Exception ex) {
			throw new RemoteProxyFailureException(
					"Failed to invoke HSF proxy for remote service [" + getServiceUrl() + "]", ex);
		} finally {
			resetThreadContextClassLoader(originalClassLoader);
		}
	}

	@Override
	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		Assert.notNull(getServiceInterface(), "'serviceInterface' is required");
		InvocationHandler handler = new HsfInvocationHandler(getServiceInterface(), getHsfServiceInterfaceName(), getServiceUrl(), getVersion());
		this.hsfProxy = Proxy.newProxyInstance(getBeanClassLoader(), new Class[]{getServiceInterface()}, handler);
	}

}
